package javango.forms.fields;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.google.inject.Inject;

import javango.forms.widgets.DateWidget;
import javango.forms.widgets.TimeWidget;
import javango.forms.widgets.WidgetFactory;

/**
 * Field that allows the user to enter time information,  the cleaned value will be a {@link java.util.Date} object with the date
 * fields set to January 1, 1970.  The time is interpreted as a 24 hour clock (1-24)
 * 
 * @author john
 *
 */
public class TimeField extends AbstractField<Date> {

	
	public static final String SHORT_TIME_FORMAT = "kk:mm";
	public static final String TIME_FORMAT = "kk:mm:ss";
	
	public final DateFormat SHORT_TIME_FORMATTER = new SimpleDateFormat(SHORT_TIME_FORMAT);
	public final DateFormat TIME_FORMATTER = new SimpleDateFormat(TIME_FORMAT);
	
	@Inject
	public TimeField(WidgetFactory factory) {
		super(factory);
		setWidget(TimeWidget.class);
	}
	
	@Override
	public Date clean(String value, Map<String, String> errors) {
		if (StringUtils.isEmpty(value)) {
			if (this.isRequired()) {
				errors.put(getName(), "Required");
				return null;
			} else {
				return null;
			}
		} else {
			boolean pm = false;
			value = value.toUpperCase();
			if (value.contains("PM") || value.contains("P.M.")) {
				pm = true;
			}
			if (!value.contains(":")) {
				// ok,  figure out how to add the : into the correct place,  we either have 3 or 4 digits....  find the first non-digit
				int index=0;
				while(index < value.length()) {
					String v = value.substring(index, index+1);
					if (!StringUtils.isNumeric(v)) break;
					index++;
				}
				if (index == 3 || index == 4) {
					value = String.format("%s:%s", value.substring(0, index-2), value.substring(index-2));
				} else {
					errors.put(this.getName(), "Unable to interpret time");
				}
			}
			
			Date returnValue = null;
			try {
				returnValue = TIME_FORMATTER.parse(value);
			} catch (ParseException e) {
				// no need to panic
			}
			if (returnValue == null) {
				try {
					returnValue = SHORT_TIME_FORMATTER.parse(value);
				} catch (ParseException e) {
					errors.put(this.getName(), e.toString());
				}
			}
			if (pm) {
				Calendar c = new GregorianCalendar();
				c.setTime(returnValue);
				if (c.get(Calendar.HOUR_OF_DAY) < 12) {
					c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY)+12);
					returnValue = c.getTime();
				}
				
			}
			return returnValue;
		}		
	}

	
}
